package com.joker.aigc.chat.service.impl;

import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.model.ObjectMetadata;
import com.aliyun.oss.model.PutObjectRequest;
import com.aliyun.oss.model.PutObjectResult;
import com.joker.aigc.chat.service.OssService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.UUID;

/**
 * 阿里云OSS服务实现类
 *
 * @author system
 * @since 2025-08-28
 */
@Slf4j
@Service
public class OssServiceImpl implements OssService {

    @Value("${oss.endpoint}")
    private String endpoint;

    @Value("${oss.keyid}")
    private String accessKeyId;

    @Value("${oss.keysecret}")
    private String accessKeySecret;

    @Value("${oss.bucketname}")
    private String bucketName;

    private OSS ossClient;

    @PostConstruct
    public void init() {
        ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
        log.info("阿里云OSS客户端初始化成功，endpoint: {}, bucket: {}", endpoint, bucketName);
    }

    @PreDestroy
    public void destroy() {
        if (ossClient != null) {
            ossClient.shutdown();
            log.info("阿里云OSS客户端已关闭");
        }
    }

    @Override
    public String uploadFile(MultipartFile file, String objectName) {
        try {
            log.info("开始上传文件到OSS: {}", objectName);
            
            // 创建ObjectMetadata并设置Content-Type
            ObjectMetadata metadata = new ObjectMetadata();
            if (file.getContentType() != null) {
                metadata.setContentType(file.getContentType());
            }
            
            PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, objectName, file.getInputStream(), metadata);
            PutObjectResult result = ossClient.putObject(putObjectRequest);
            String url = generateFileUrl(objectName);
            log.info("文件上传成功: {}, ETag: {}", url, result.getETag());
            return url;
        } catch (Exception e) {
            log.error("文件上传失败: {}", e.getMessage(), e);
            throw new RuntimeException("文件上传失败: " + e.getMessage());
        }
    }

    @Override
    public String uploadFile(File file, String objectName) {
        try {
            log.info("开始上传文件到OSS: {}", objectName);
            PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, objectName, file);
            PutObjectResult result = ossClient.putObject(putObjectRequest);
            String url = generateFileUrl(objectName);
            log.info("文件上传成功: {}, ETag: {}", url, result.getETag());
            return url;
        } catch (Exception e) {
            log.error("文件上传失败: {}", e.getMessage(), e);
            throw new RuntimeException("文件上传失败: " + e.getMessage());
        }
    }

    @Override
    public String uploadImage(MultipartFile imageFile) {
        // 生成图片文件名
        String originalFilename = imageFile.getOriginalFilename();
        String extension = "";
        if (originalFilename != null && originalFilename.contains(".")) {
            extension = originalFilename.substring(originalFilename.lastIndexOf("."));
        }
        
        // 生成唯一文件名
        String fileName = generateUniqueFileName("images", extension);
        return uploadFile(imageFile, fileName);
    }

    @Override
    public String uploadJsonFile(String jsonContent, String fileName) {
        try {
            // 确保文件名以.json结尾
            if (!fileName.endsWith(".json")) {
                fileName = fileName + ".json";
            }
            
            // 生成JSON文件路径，使用传入的文件名作为基础
            String objectName = "json/" + fileName;
            
            log.info("开始上传JSON文件到OSS: {}", objectName);
            
            // 将JSON内容转换为字节数组
            byte[] jsonBytes = jsonContent.getBytes(StandardCharsets.UTF_8);
            ByteArrayInputStream inputStream = new ByteArrayInputStream(jsonBytes);
            
            // 创建ObjectMetadata并设置Content-Type
            ObjectMetadata metadata = new ObjectMetadata();
            metadata.setContentType("application/json");
            
            // 上传到OSS
            PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, objectName, inputStream, metadata);
            PutObjectResult result = ossClient.putObject(putObjectRequest);
            
            String url = generateFileUrl(objectName);
            log.info("JSON文件上传成功: {}, ETag: {}", url, result.getETag());
            return url;
        } catch (Exception e) {
            log.error("JSON文件上传失败: {}", e.getMessage(), e);
            throw new RuntimeException("JSON文件上传失败: " + e.getMessage());
        }
    }

    @Override
    public void deleteFile(String objectName) {
        try {
            ossClient.deleteObject(bucketName, objectName);
            log.info("文件删除成功: {}", objectName);
        } catch (Exception e) {
            log.error("文件删除失败: {}", e.getMessage(), e);
            throw new RuntimeException("文件删除失败: " + e.getMessage());
        }
    }

    /**
     * 生成文件访问URL
     *
     * @param objectName 对象名称
     * @return 文件访问URL
     */
    private String generateFileUrl(String objectName) {
        return "https://" + bucketName + "." + endpoint + "/" + objectName;
    }

    /**
     * 生成唯一文件名
     *
     * @param directory 目录名
     * @param extension 文件扩展名
     * @return 唯一文件名
     */
    private String generateUniqueFileName(String directory, String extension) {
        String timestamp = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss"));
        String uuid = UUID.randomUUID().toString().replace("-", "");
        return directory + "/" + timestamp + "_" + uuid + extension;
    }
}
